package jmetal.util.dir;

import jmetal.core.Solution;
import jmetal.core.SolutionSet;
import jmetal.util.MatrixUtil;

public class OccupyFitness {

	private SolutionSet solutionSet;
	
	public OccupyFitness(SolutionSet solutionSet) {
		this.solutionSet = solutionSet;
	}

	public void assignFitness(double[][] vectors, double[] zideal, double[] intercepts) {
		double[][] normMatrix = normalizeSolutionSet(zideal,intercepts);
		int[] occupyArray = getOccupyCountArray(normMatrix, vectors);
		
		for(int i = 0;i<solutionSet.size();i++){
			Solution solution = solutionSet.get(i);
			double fitness = 1.0/(double)(occupyArray[i]+1.0);
			solution.setFitness(fitness);
		}
		
	}

	private double[][] normalizeSolutionSet(double[] zideal, double[] intercepts) {
		int popsize = solutionSet.size();
		int objNum = zideal.length;
		double[][] normSetMatrix = new double[popsize][objNum];
		for(int i = 0;i<popsize;i++){
			Solution solution = solutionSet.get(i);
			for(int j = 0;j<objNum;j++){
				normSetMatrix[i][j] = (solution.getObjective(j)-zideal[j])/(intercepts[j]-zideal[j]);
			}
		}
		return normSetMatrix;
	}
	
	/**
	 * 获取绑定参考线个数数组
	 * @param compSet
	 * @param vectors
	 * @return
	 */
	public int[] getOccupyCountArray(double[][] solutionSetMatrix, double[][] vectors) {
		int [] counts = new int[solutionSetMatrix.length];
		for(int i = 0;i<counts.length;i++)
			counts[i] = 0;
		
		for(int i = 0;i<vectors.length;i++){
			int minSub = 0;
			double minAngle = 0;			
			
			for(int j = 0;j<solutionSetMatrix.length;j++){
				double[] objectives = solutionSetMatrix[j];
//				objectives = adaptObjectives(objectives);
				double innerProd = 0;
				for(int dim = 0;dim<vectors[i].length;dim++){
					double x1 = vectors[i][dim];
					double x2 = objectives[dim];
					innerProd =innerProd + (x1*x2);
				}
				double tempAngle = innerProd/ (MatrixUtil.norm(vectors[i])*MatrixUtil.norm(objectives));
					
				if(tempAngle>minAngle){
					minAngle = tempAngle;
					minSub = j;
				}
			}
			counts[minSub]++;
		}
		return counts;
	}

	public void assignFitness(double[][] vectors) {
		double[][] normSetMatrix = new double[solutionSet.size()][solutionSet.get(0).getNumberOfObjectives()];
		for(int i = 0;i<solutionSet.size();i++){
			Solution solution = solutionSet.get(i);
			for(int j = 0;j<solution.getNumberOfObjectives();j++){
				normSetMatrix[i][j] = solution.getObjective(j);
			}
		}
		int[] occupyArray = getOccupyCountArray(normSetMatrix, vectors);
		
		for(int i = 0;i<solutionSet.size();i++){
			Solution solution = solutionSet.get(i);
			double fitness = 1.0/(double)(occupyArray[i]+1.0);
			solution.setFitness(fitness);
		}
		
	}

}
